/*
	This file is part of GTimer.

    GTimer is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License\.

    GTimer is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with GTimer. If not, see <http://www.gnu.org/licenses/>.
	
	Copyright 2012 Muhammad Ghareeb Sideek
	Contact: MGhareeb64@gmail.com
 */

package com.gsourcecode.timer;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;

import android.app.Activity;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.Shader.TileMode;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Bundle;
import android.os.Environment;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.Vibrator;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnKeyListener;
import android.view.View.OnTouchListener;
import android.view.Window;
import android.widget.TextView;
import android.widget.Toast;

import com.gsourcecode.command.Command;
import com.gsourcecode.utils.Colors;
import com.gsourcecode.utils.Gradient;

public class GTimerPlay extends Activity implements OnInitListener, OnKeyListener, OnTouchListener {

	public TextToSpeech tts;
	private int MY_DATA_CHECK_CODE = 0;

	private Vibrator v;

	private TextView txvTime, txvText, txvSub;
	private ArrayList<String> fin = new ArrayList<String>();

	public static Timer timer;
	private long startTime, pauseTime, pauseDuration = 0;
	private boolean pause = false;

	private ArrayList<Command> cmds;
	private int cmdsI = 0;
	private SoundPool pool;
	private int beep;
	private WakeLock wakeLock;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);

		v = (Vibrator) getSystemService(Service.VIBRATOR_SERVICE);

		setContentView(R.layout.play);

		txvText = (TextView) findViewById(R.id.text);
		txvSub = (TextView) findViewById(R.id.txvTextSub);
		txvTime = (TextView) findViewById(R.id.time);
		txvTime.setOnTouchListener(this);
		txvTime.setOnKeyListener(this);
		txvTime.setFocusableInTouchMode(true);
		txvTime.requestFocus();

		readGTimerFile();
		perpareFin();
		if (timer != null) {
			timer.cancel();
			timer.purge();
		}
		timer = new Timer(true);
		timer.scheduleAtFixedRate(new MainLoopTask(), 200, 100);

		Intent checkIntent = new Intent();
		checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
		startActivityForResult(checkIntent, MY_DATA_CHECK_CODE);

		wakeLock = ((PowerManager) getSystemService(Context.POWER_SERVICE)).newWakeLock(PowerManager.FULL_WAKE_LOCK, "Lockation");

		pool = new SoundPool(2, AudioManager.STREAM_NOTIFICATION, 0);
		try {
			beep = pool.load(getAssets().openFd("beep.ogg"), 1);
		} catch (IOException e) {}

		timer.schedule(new GTimerResetTask(), 100);
		startTime = Calendar.getInstance().getTimeInMillis() + 100;
		pauseResume();
	}

	@Override
	protected void onResume() {
		super.onResume();
		try {
			if (Settings.get().isWakeLock)
				wakeLock.acquire();
		} catch (Exception e) {}
	}

	@Override
	protected void onPause() {
		super.onPause();
		try {
			wakeLock.release();
		} catch (Exception e) {}
	}

	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (requestCode == MY_DATA_CHECK_CODE) {
			if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS && tts == null) {
				tts = new TextToSpeech(this, this);
			} else {
				Intent installIntent = new Intent();
				installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
				startActivity(installIntent);
			}
		}
	}

	@Override
	public void onInit(int status) {
		if (status != TextToSpeech.SUCCESS)
			Toast.makeText(this, "Error occurred while initializing Text-To-Speech engine", Toast.LENGTH_LONG).show();
	}

	@Override
	public void onAttachedToWindow() {
		super.onAttachedToWindow();
		getWindow().setFormat(PixelFormat.RGBA_8888);
	}

	// TOUCH

	@Override
	public boolean onTouch(View v, MotionEvent e) {
		if (e.getAction() == MotionEvent.ACTION_UP)
			pauseResume();
		return true;
	}

	// KEYS

	@Override
	public boolean onKey(View v, int keyCode, KeyEvent e) {
		try {
			if (e.getAction() == KeyEvent.ACTION_UP) {
				switch (e.getKeyCode()) {
				case KeyEvent.KEYCODE_BACK:
					if (pause) {
						tts.stop();
						startActivity(new Intent(this, Class.forName("com.gsourcecode.timer.GTimerMain")));
						tts.shutdown();
						finish();
					} else {
						Toast.makeText(this, "Press again to stop the GTimer.", Toast.LENGTH_LONG).show();
						pauseResume();
					}
					break;
				case KeyEvent.KEYCODE_ENTER:
					pauseResume();
					break;
				default:
					break;
				}
			}
		} catch (Exception e1) {}
		return true;
	}

	// FILE

	@SuppressWarnings("unchecked")
	private synchronized void readGTimerFile() {
		cmds = Command.wrongList();
		try {
			if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
				String p = Environment.getExternalStorageDirectory().getAbsolutePath();
				p += File.separator + "gtimer" + File.separator + "temp";
				ObjectInputStream in = new ObjectInputStream(new FileInputStream(new File(p)));
				cmds = (ArrayList<Command>) in.readObject();
				in.close();
			}
		} catch (Exception e) {
			cmds = Command.wrongList();
		}
		cmds.add(0, new Command(0, 0, "", ""));
	}

	private void perpareFin() {
		try {
			if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
				File f = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "gtimer" + File.separator + "fin.ptf");
				if (f.exists() && f.isFile()) {
					Scanner s = new Scanner(f);
					while (s.hasNext())
						fin.add(s.nextLine());
					s.close();
				} else {
					f.createNewFile();
					PrintWriter out = new PrintWriter(f);
					out.write("Bloody amazing!\nMarvellous!\nWell done!");
					out.close();
					fin.add("Bloody amazing!");
					fin.add("Marvellous!");
					fin.add("Well done!");
				}
			}
		} catch (Exception e) {}
	}

	// TIMER

	private synchronized String finRandom() {
		if (fin.isEmpty())
			return "";
		return fin.get((int) (Math.random() * fin.size()));
	}

	private void pauseResume() {
		if (cmdsI >= cmds.size())
			return;
		if (pause) {
			pauseDuration += Calendar.getInstance().getTimeInMillis() - pauseTime;
			timer.schedule(new GTimerResetTask(), 100);
		} else {
			pauseTime = Calendar.getInstance().getTimeInMillis();
		}
		pause = !pause;
	}

	class MainLoopTask extends TimerTask {

		long t;

		@Override
		public void run() {
			// time
			if (pause)
				t = pauseTime - startTime - pauseDuration;
			else {
				pool.play(beep, 0, 0, 0, 0, 1);
				t = Calendar.getInstance().getTimeInMillis() - startTime - pauseDuration;
			}
			t *= Settings.get().skip;
			// display time & pause
			runOnUiThread(new Runnable() {
				@Override
				public void run() {
					txvTime.setText(String.format("%02d:%02d:%02d", (t / 60 / 60 / 1000), (t / 60 / 1000) % 60, (t / 1000) % 60));
					// pause
					if (pause) {
						txvTime.setBackgroundColor(0xFFFF1100);
						txvTime.setTextColor(0xFFFFFFFF);
					}
				}
			});
			// cmds
			if (!pause && cmdsI < cmds.size() && t > cmds.get(cmdsI).time) {
				++cmdsI;
				if (cmdsI == cmds.size()) {
					timer.schedule(new GTimerTask(new Command(-1, Color.BLACK, "Finished!", finRandom())), 10);
					cmdsI--;
					if (!pause)
						pauseResume();
					cmdsI++;
				} else {
					timer.schedule(new GTimerTask(cmds.get(cmdsI)), 10);
					timer.schedule(new GTimerResetTask(), 400);
				}
			}
		}
	}

	class GTimerTask extends TimerTask {
		private String text, sub;
		private int color;

		public GTimerTask(Command c) {
			this.text = c.title;
			this.sub = c.sub;
			this.color = c.color;
		}

		@Override
		public void run() {
			if (Settings.get().isBeep)
				pool.play(beep, Settings.get().beepVol, Settings.get().beepVol, 0, 0, 1);
			if (Settings.get().isTTS) {
				tts.stop();
				tts.setPitch(Settings.get().ttsPitch);
				tts.setSpeechRate(Settings.get().ttsRate);
				tts.speak(text + "... " + sub, TextToSpeech.QUEUE_ADD, null);
			}
			if (Settings.get().isVib)
				v.vibrate(Settings.get().vibDur);
			runOnUiThread(new Runnable() {
				@Override
				public void run() {
					// text
					txvText.setText(text);
					txvText.setTextColor(Color.WHITE);
					txvSub.setText(sub);
					txvSub.setTextColor(Color.WHITE);

					// bg
					int w = getWindowManager().getDefaultDisplay().getWidth();
					int h = getWindowManager().getDefaultDisplay().getHeight();
					txvSub.setBackgroundDrawable(Gradient.getRad(w / 2, h / 2, h, color, Colors.dark(color), TileMode.CLAMP));
					txvText.setBackgroundDrawable(Gradient.getRad(w / 2, 0, h, color, Colors.dark(color, 3), TileMode.CLAMP));

					// time
					txvTime.setBackgroundColor(0xFF88AA00);
					txvTime.setTextColor(0xFFFFFFFF);
				}
			});
		}

	}

	public class GTimerResetTask extends TimerTask {

		@Override
		public void run() {
			runOnUiThread(new Runnable() {
				@Override
				public void run() {
					txvTime.setBackgroundColor(0xFFFFFFFF);
					txvTime.setTextColor(0xFF000000);
				}
			});
		}
	}
}
